package com.wiseman.runner;

import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Timer;
import java.util.TimerTask;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.app.PendingIntent.CanceledException;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import cn.domob.android.ads.DomobInterstitialAd;

import com.bill.guidelib.GuideLibActivity;
import com.bill.guidelib.GuideLibConstValue;

public class MainActivity extends Activity implements OnClickListener,
		ConstValue, GuideLibConstValue, LocationListener {

	TextView mTvTime = null;
	TextView mTvDistance = null;
	TextView mTvSpeed = null;
	TextView mTvVelocity = null;

	LocationManager myLocationManager = null;

	Timer myTimer = null;
	int myPastMinutes = 0;
	long myStartMs = 0;
	float myDistance = 0;
	float mySpeed = 0;
	float myVelocity = 0;

	// for location.
	double myLastLongititude = 0;
	double myLastLatitude = 0;
	long myLastMsByLocation = 0;

	String mStartAddress = null;
	String mEndAddress = null;

	// for preference.
	String mLocationProvider = DEFAULT_LOCATION_PROVIDER;
	long mIntervalTime = DEFAULT_INTERVAL_TIME;
	float mIntervalDistance = DEFAULT_INTERVAL_DISTANCE;

	// for introduce.
	int mImgRes[] = { R.drawable.intro1, R.drawable.intro2, R.drawable.intro4,
			R.drawable.intro5 };
	int mTxtRes[] = { -1 };

	int REQUESTCODE_INTRO = 1;
	private DomobInterstitialAd mInterstitialAd;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		Button bt = (Button) findViewById(R.id.start);
		bt.setOnClickListener(this);

		bt = (Button) findViewById(R.id.stop);
		bt.setOnClickListener(this);

		bt = (Button) findViewById(R.id.history);
		bt.setOnClickListener(this);

		bt = (Button) findViewById(R.id.config);
		bt.setOnClickListener(this);

		// bt = (Button) findViewById(R.id.moreApp);
		// bt.setOnClickListener(this);

		mTvTime = (TextView) findViewById(R.id.time_value);
		mTvDistance = (TextView) findViewById(R.id.distance_value);
		mTvSpeed = (TextView) findViewById(R.id.speed_value);
		mTvVelocity = (TextView) findViewById(R.id.volocity_value);

		// Bitmap bitmap = ((BitmapDrawable)
		// (getResources().getDrawable(R.drawable.bg3))).getBitmap();
		// BitmapDrawable bd = new BitmapDrawable(toRoundCorner(bitmap, 5));
		// findViewById(R.id.speedBar).setBackgroundDrawable(bd);
		// findViewById(R.id.velocityBar).setBackgroundDrawable(bd);
		findViewById(R.id.velocityBar).setBackgroundResource(R.drawable.bg3);
		findViewById(R.id.speedBar).setBackgroundResource(R.drawable.bg3);
		findViewById(R.id.timeBar).setBackgroundResource(R.drawable.bg3);
		findViewById(R.id.distanceBar).setBackgroundResource(R.drawable.bg3);

		myLocationManager = (LocationManager) getSystemService(LOCATION_SERVICE);

		// show intro.
		showIntro();

		reset();

		// for test.
		// mTvTime.setText("03:14");
		// mTvDistance.setText("8.28");
		// mTvSpeed.setText("11.01");
		// mTvVelocity.setText("06.18");

		DomoAd.checkUpdate(this);
		DomoAd.createBar(this);

		WLog.createLog(getCacheDir().getAbsolutePath(), "log.txt", "create");

		// mInterstitialAd = DomoAd.createInterstitialAd(this);
	}

	void showIntro() {
		SharedPreferences preferences = getSharedPreferences(PREFS_NAME,
				MODE_PRIVATE);
		int count = preferences.getInt("count", 0);

		// 判断程序与第几次运行，如果是第一次运行则跳转到引导页面
		if (count == 0) {
			Intent introIntent = new Intent();
			introIntent.setClass(this, GuideLibActivity.class);
			introIntent.putExtra(IMAGE_RES, mImgRes);
			introIntent.putExtra(TEXT_RES, mTxtRes);
			introIntent.putExtra(BUTTON_STRING, "开 始使用");
			introIntent.putExtra(BUTTON_YPOS, 40);

			startActivityForResult(introIntent, REQUESTCODE_INTRO);

			// 存入数据
			Editor editor = preferences.edit();
			editor.putInt("count", ++count);
			editor.commit();
		}
	}

	@Override
	protected void onDestroy() {
		// 关闭GPS
		if (myLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
			toggleGPS();
		}

		if (myTimer != null) {
			myTimer.cancel();
			myTimer = null;
		}

		super.onDestroy();
	}

	static final int MSG_UPDATE_TIME = 0;
	static final int MSG_UPDATE_DISTANCE = 1;
	static final int MSG_UPDATA_LOG = 2;
	static final int MSG_UPDATE_SPEED = 3;
	static final int MSG_UPDATE_VELOCITY = 4;

	final Handler myHandler = new Handler() {
		public void handleMessage(android.os.Message msg) {

			switch (msg.what) {
			case MSG_UPDATE_TIME:
				mTvTime.setText((CharSequence) msg.obj);
				break;
			case MSG_UPDATE_DISTANCE:
				mTvDistance.setText((CharSequence) msg.obj);
				break;
			case MSG_UPDATE_SPEED:
				mTvSpeed.setText((CharSequence) msg.obj);
				break;
			case MSG_UPDATE_VELOCITY:
				mTvVelocity.setText((CharSequence) msg.obj);
				break;
			case MSG_UPDATA_LOG:
				break;
			default:
				break;
			}
		};
	};

	void sendMessage(int what, String txt) {

		Message msg = new Message();
		msg.what = what;
		msg.obj = txt;

		myHandler.sendMessage(msg);
	}

	void outLog(String msg) {
		// final DateFormat sdf = new SimpleDateFormat(DATE_FORMAT, Locale.US);
		// myLog.append(sdf.format(new Date()) + msg + "\r\n");
		// sendMessage(MSG_UPDATA_LOG, myLog.toString());
		WLog.writerLogInfo(msg);
	}

	void toggleGPS() {
		Intent GPSIntent = new Intent();
		GPSIntent.setClassName("com.android.settings",
				"com.android.settings.widget.SettingsAppWidgetProvider");
		GPSIntent.addCategory("android.intent.category.ALTERNATIVE");
		GPSIntent.setData(Uri.parse("custom:3"));
		try {
			PendingIntent.getBroadcast(this, 0, GPSIntent, 0).send();
		} catch (CanceledException e) {
			e.printStackTrace();
		}
	}

	@Override
	public void onClick(View v) {
		int id = v.getId();

		switch (id) {
		case R.id.start:
			start();
			break;
		case R.id.stop:
			stop();
			break;
		case R.id.history:
			showHistory();
			break;
		case R.id.config:
			// DomoAd.showInterstitialAd(this, mInterstitialAd);
			showPreference();
			break;
		default:
			break;
		}

	}

	private void showPreference() {
		Intent intent = new Intent();
		intent.setClass(this, MyPreferenceActivity.class);
		startActivityForResult(intent, REQUEST_PREFERENCE);
	}

	private void showHistory() {
		Intent intent = new Intent();
		intent.setClass(this, HistoryActivity.class);
		startActivity(intent);
	}

	private void startSaveActivity() {
		Intent intent = new Intent();
		TripData data = new TripData(myDistance, myPastMinutes);
		data.mStartAddress = mStartAddress;
		data.mEndAddress = mEndAddress;
		intent.putExtra(INTENT_DATA_TRIPDATA, data);
		intent.setAction(INTENT_ACTION_NEW);
		intent.setClass(this, TrapInfoActivity.class);

		startActivity(intent);
	}

	void reset() {

		myPastMinutes = 0;
		myDistance = 0;
		mySpeed = 0;
		myVelocity = 0;

		myLastLongititude = 0;
		myLastLatitude = 0;
		myLastMsByLocation = 0;

		mTvTime.setText("00:00");
		mTvDistance.setText("0.00");
		mTvSpeed.setText("0.00");
		mTvVelocity.setText("0.00");
	}

	private void start() {
		if (myTimer != null)
			return;

		outLog("start.");

		reset();

		getPreferencesConfig();

		if (myLocationManager.isProviderEnabled(mLocationProvider)) {
			// outLog("Location provider has opened.");
		} else if (LocationManager.GPS_PROVIDER.equals(mLocationProvider)) {
			// outLog("open GPS.");
			toggleGPS();
		} else if (LocationManager.NETWORK_PROVIDER.equals(mLocationProvider)) {
			// outLog("open other location system.");
		}

		try {
			myLocationManager.requestLocationUpdates(mLocationProvider,
					mIntervalTime, mIntervalDistance, this);
		} catch (Exception e) {
			e.printStackTrace();
			Toast toast = Toast.makeText(this, R.string.checkGPS,
					Toast.LENGTH_SHORT);
			toast.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, 50);
			toast.show();
			return;
		}

		myStartMs = System.currentTimeMillis();
		myTimer = new Timer();
		myTimer.schedule(new TimerTask() {

			@Override
			public void run() {

				long curMs = System.currentTimeMillis();
				long pastSeconds = (curMs - myStartMs) / 1000;
				int pastMinutes = (int) (pastSeconds / 60);

				// 如果小于一小时，按分：秒显示，否则按时：分显示。
				String timeStr = null;
				if (pastMinutes < 60) {
					timeStr = String.format("%02d:%02d", pastMinutes,
							pastSeconds % 60);
				} else {
					timeStr = String.format("%02d:%02d", pastMinutes / 60,
							pastMinutes % 60);
				}
				sendMessage(MSG_UPDATE_TIME, timeStr);

				if (myPastMinutes != pastMinutes && pastMinutes != 0) {
					mySpeed = myDistance * 60 / pastMinutes;
					sendMessage(MSG_UPDATE_SPEED,
							String.format("%.2f", mySpeed));
					myPastMinutes = pastMinutes;
				}

				long pastMsOfVelocity = curMs - myLastMsByLocation;

				if (pastMsOfVelocity / 1000 > 60 && myVelocity != 0) {
					// if stay over 60s, reset velocity.
					myVelocity = 0;
					sendMessage(MSG_UPDATE_VELOCITY,
							String.format("%.2f", 0.0f));
					outLog("Reset velocity. ");
				}
			}
		}, 1000, 1000);

	}

	private void stop() {
		if (myTimer == null)
			return;

		outLog("stop.");

		myTimer.cancel();
		myTimer = null;

		// 关闭GPS
		if (myLocationManager.isProviderEnabled(mLocationProvider)) {
			myLocationManager.removeUpdates(this);
			// toggleGPS();
		}

		// 如果记录不为空，存储记录。
		if (myPastMinutes != 0 && myDistance != 0) {
			// for test.
			// mStartAddress = getAddressByTitude(34.1756980,108.8787560);
			// mEndAddress = getAddressByTitude(34.2319550,108.8971070);

			mEndAddress = getAddressByTitude(myLastLongititude, myLastLatitude);
			startSaveActivity();

		}

		reset();
	}

	void showSaveDialog() {

		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setTitle("提示").setIcon(android.R.drawable.ic_dialog_alert)
				.setMessage("是否存储当前记录?")
				.setPositiveButton("是", new DialogInterface.OnClickListener() {
					public void onClick(DialogInterface dialog, int id) {
						stop();
						finish();
					}
				})
				.setNegativeButton("否", new DialogInterface.OnClickListener() {
					public void onClick(DialogInterface dialog, int id) {
						dialog.cancel();
						finish();
					}
				});

		builder.show();
	}

	public boolean onKeyDown(int keyCode, KeyEvent event) {
		if (keyCode == KeyEvent.KEYCODE_BACK) {
			if (myPastMinutes != 0 && myDistance != 0) {
				showSaveDialog();
			}
		}

		return super.onKeyDown(keyCode, event);
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {

		// if (requestCode == REQUEST_PREFERENCE) {
		// getPreferencesConfig();
		// }

		super.onActivityResult(requestCode, resultCode, data);
	}

	private void getPreferencesConfig() {
		String vstr = null;

		SharedPreferences sp = getSharedPreferences(PREFS_NAME, MODE_PRIVATE);

		mLocationProvider = sp.getString(KEY_LOCATION_METHOD,
				DEFAULT_LOCATION_PROVIDER);

		vstr = sp.getString(KEY_INTERVAL_TIME,
				Integer.toString(DEFAULT_INTERVAL_TIME));
		try {
			mIntervalTime = Long.parseLong(vstr);
		} catch (NumberFormatException e) {
			mIntervalTime = DEFAULT_INTERVAL_TIME;
		}

		vstr = sp.getString(KEY_INTERVAL_DISTANCE,
				Integer.toString(DEFAULT_INTERVAL_DISTANCE));
		try {
			mIntervalDistance = Long.parseLong(vstr);
		} catch (NumberFormatException e) {
			mIntervalDistance = DEFAULT_INTERVAL_DISTANCE;
		}

	}

	/**
	 * 将图片设置为圆角
	 */
	public static Bitmap toRoundCorner(Bitmap bitmap, int pixels) {
		Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
				bitmap.getHeight(), Config.ARGB_8888);
		Canvas canvas = new Canvas(output);
		final int color = 0xff424242;
		final Paint paint = new Paint();
		final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
		final RectF rectF = new RectF(rect);
		final float roundPx = pixels;
		paint.setAntiAlias(true);
		canvas.drawARGB(0, 0, 0, 0);
		paint.setColor(color);

		Path p = new Path();
		p.lineTo(rect.right, 0);
		p.lineTo(rect.right - pixels, rect.bottom);
		p.lineTo(pixels, rect.bottom);
		p.lineTo(0, 0);

		// canvas.drawPath(p, paint);
		canvas.drawRoundRect(rectF, roundPx, roundPx * 1.5f, paint);
		// canvas.drawOval(rectF, paint);
		paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
		canvas.drawBitmap(bitmap, rect, rect, paint);
		return output;
	}

	String getAddressByTitude(double longititude, double latitude) {
		String address = null;
		final String webAPI = "http://maps.google.com/maps/api/geocode/xml?latlng=%f,%f&sensor=true&language=zh-CN";

		String requestStr = String.format(webAPI, longititude, latitude);

		// Intent intent = new Intent(Intent.ACTION_VIEW);
		// intent.setData(Uri.parse(requestStr));
		// startActivity(intent);

		// try {
		// URL url = new URL(requestStr);
		//
		// HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
		//
		// int nRC = urlConn.getResponseCode();
		// if (nRC == HttpURLConnection.HTTP_OK) {
		//
		// SAXParserFactory spf = SAXParserFactory.newInstance();
		// SAXParser sp = spf.newSAXParser();
		// XMLReader xr = sp.getXMLReader();
		// AddressContentHandler addressHandler = new AddressContentHandler();
		// xr.setContentHandler(addressHandler);
		//
		// xr.parse(new InputSource(urlConn.getInputStream()));
		// address = addressHandler.getAddress();
		// urlConn.disconnect();
		// }
		//
		// } catch (Exception e) {
		// e.printStackTrace();
		// outLog(e.toString());
		// }

		if (address == null) {
			address = String.format("(%.4f, %.4f)", longititude, latitude);
		}

		return address;
	}

	@Override
	public void onLocationChanged(Location location) {
		final double longititude = location.getLongitude();
		final double latitude = location.getLatitude();
		float[] results = new float[2];

		if (myTimer == null) {
			return;
		}

		long curMs = System.currentTimeMillis();

		if (myLastLongititude == 0 && myLastLatitude == 0) {
			myLastLongititude = longititude;
			myLastLatitude = latitude;
			myLastMsByLocation = curMs;
			mStartAddress = getAddressByTitude(longititude, latitude);
			return;
		}

		Location.distanceBetween(myLastLatitude, myLastLongititude, latitude,
				longititude, results);
		myDistance += results[0] / 1000;

		sendMessage(MSG_UPDATE_DISTANCE, String.format("%.2f", myDistance));

		long costMs = curMs - myStartMs;
		if (costMs > 0) {
			mySpeed = myDistance * 1000 * 60 * 60 / costMs;
			sendMessage(MSG_UPDATE_SPEED, String.format("%.2f", mySpeed));
		}

		long deltaMs = curMs - myLastMsByLocation;
		if (deltaMs > 0) {
			myVelocity = results[0] * 60 * 60 / deltaMs;
			sendMessage(MSG_UPDATE_VELOCITY, String.format("%.2f", myVelocity));
		}

		myLastLongititude = longititude;
		myLastLatitude = latitude;
		myLastMsByLocation = curMs;

		outLog(String.format("(%.4f, %.4f), Distance = %.2fm",
				myLastLongititude, myLastLatitude, results[0]));
	}

	@Override
	public void onStatusChanged(String provider, int status, Bundle extras) {
		// TODO Auto-generated method stub
	}

	@Override
	public void onProviderEnabled(String provider) {
		// TODO Auto-generated method stub
	}

	@Override
	public void onProviderDisabled(String provider) {
		// TODO Auto-generated method stub
	}

}
